﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Nvigorate.Data;
using Nvigorate.Relational.Mapping.Index;
using Nvigorate.Relational.UnitOfWork;
using Nvigorate.TestObjects;

namespace Nvigorate.Test.Relational.UnitOfWork
{
    [TestClass]
    public class ImmediateUnitOfWorkTests
    {
        [TestMethod]
        public void Persist_CallsExecuteCommand()
        {
            // Arrange
            var repositoryMapIndex = new Mock<IRepositoryMapIndex>();
            var dataInterface = new Mock<IDataInterface>();
            var command = new Mock<ICommand>();
            // Increment count when execute command is called
            var count = 0;
            command.Expect(c => c.Execute()).Callback(() => count++);

            var person = new Person();
            var unitOfWork = new UnitOfWorkHarness(repositoryMapIndex.Object, dataInterface.Object)
                                 {
                                     PersistCommandMock = command
                                 };

            // Act
            unitOfWork.Persist(person, false);

            // Assert
            Assert.AreEqual(1, count);
        }

        public void Delete_CallsExecuteCommand()
        {
            // Arrange
            var repositoryMapIndex = new Mock<IRepositoryMapIndex>();
            var dataInterface = new Mock<IDataInterface>();
            var command = new Mock<ICommand>();
            // Increment count when execute command is called
            var count = 0;
            command.Expect(c => c.Execute()).Callback(() => count++);

            var person = new Person();
            var unitOfWork = new UnitOfWorkHarness(repositoryMapIndex.Object, dataInterface.Object)
                                 {
                                     DeleteCommandMock = command
                                 };

            // Act
            unitOfWork.Delete(person, false, true);

            // Assert
            Assert.AreEqual(1, count);
        }

        #region Nested Types

        private class UnitOfWorkHarness : ImmediateUnitOfWork
        {
            public IMock<ICommand> PersistCommandMock { get; set; }
            public IMock<ICommand> DeleteCommandMock { get; set; }

            public UnitOfWorkHarness(IRepositoryMapIndex repositoryMapIndex, IDataInterface dataInterface)
                : base(repositoryMapIndex, dataInterface)
            {
            }

            protected override ICommand CreatePersistCommand(object instance, bool enforceConcurrency)
            {
                return PersistCommandMock.Object;
            }

            protected override ICommand CreateDeleteCommand(object instance, bool recursive, bool enforceConcurrency)
            {
                return DeleteCommandMock.Object;
            }
        }

        #endregion
    }
}